package com.wiloon.java8x.thread;

/*
 * Created by wiloon on 3/26/17;
 */

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumer {
    public static void main(String args[]) {
        Resources res = new Resources();
        Producer pro = new Producer(res);
        Consumer con = new Consumer(res);
        Thread t1 = new Thread(pro);  //生产者..
        Thread t2 = new Thread(pro);  //生产者..
        Thread t3 = new Thread(pro);  //生产者..
        Thread t4 = new Thread(con);  //生产者..
        Thread t5 = new Thread(con);  //生产者..
        Thread t6 = new Thread(con);  //生产者..

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
    }
}

class Resources {
    private int count = 1;
    private boolean flag;

    private final Lock lock = new ReentrantLock();  //创建一个Lock的实例
    private Condition condition_Pro = lock.newCondition(); //创建一个控制Producer线程的Condition实例
    private Condition condition_Con = lock.newCondition();//创建一个控制Consumer线程的condition实例

    void set(String name) throws InterruptedException {
        lock.lock();  //开启锁
        try {
            while (flag)  //需要持续判断锁，如果为true，需要等待
                condition_Pro.await();   //Producer线程等待。

            String name1 = name + "--" + (++count);
            System.out.println(Thread.currentThread().getName() + "...生产者..." + name1);
            flag = true;
            condition_Con.signal(); //唤醒Customer的线程
        } finally {
            lock.unlock();   //无论程序是否执行完，都要释放资源
        }

    }

    public void out() throws InterruptedException {
        lock.lock();
        try {
            while (!flag)  //当flag为false时，没有生成，消费者需要等待
                condition_Con.await();  //消费者线程等待

            System.out.println(Thread.currentThread().getName() + ".......消费者........." + count);
            flag = false;
            condition_Pro.signal();  //唤醒Producer的线程
        } finally {
            lock.unlock();
        }

    }
}

class Producer implements Runnable {
    private Resources res;

    Producer(Resources res) {
        this.res = res;
    }

    public void run() {
        //重复执行生产的方法
        try {

            String name = "lzl";
            //noinspection InfiniteLoopStatement
            while (true)
                res.set(name);
        } catch (InterruptedException ignored) {
        }
    }
}

class Consumer implements Runnable {
    private Resources res;

    Consumer(Resources res) {
        this.res = res;
    }

    public void run() {
        //重复执行消费的方法
        try {
            //noinspection InfiniteLoopStatement
            while (true)
                res.out();
        } catch (InterruptedException ignored) {
        }
    }
}